﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace _020_021_022事件详解_7事件完整声明
{
    class Program
    {
        static void Main(string[] args)
        {
            //1.事件拥有者
            Customer customer = new Customer();
            //2/事件响应者
            Waiter waiter = new Waiter();
            //Order 事件成员 订阅事件
            customer.Order += waiter.Action;
            customer.Action();
            customer.PayBill();
        }
    }

    //传递消息类
    public class OrderEventAgrs : EventArgs
    {
        public string DishName { get; set; }
        public string Size { get; set; }
    }

    /// <summary>
    /// 委托也是一种类型  声明返回值为NULL的委托 
    /// </summary>
    /// 
    //   OrderEventHandler(Customer customer, OrderEventAgrs e)
    // OrderEventHandler 名称意义  1. 说明这是委托的事件   2. 约束事件处理器           3.存储事件处理器    


    //没有必要声明委托  .NET已经准备好委托类型
    //public delegate void OrderEventHandler(Customer customer, OrderEventAgrs e);


    //事件是基于委托的  事件响应者和发送者应该能匹配上且相互通信
    public class Customer
    {
        //存储事件处理器的字段  
        //此时  orderEventHandler  归属于类的内部 
        /// <summary>
        /// 因为 event 关键字的作用就是封装委托，它只对外暴露 += 和 -= 操作。
        /// /在类的外部，你无法访问到事件背后的委托字段，因此无法直接调用它。这是 C# 语言为了保证事件安全而设计的。
        /// </summary>
        private EventHandler orderEventHandler;

        //EventHandler 类中
        //public delegate void EventHandler(object sender, EventArgs e);


        //触发事件会自动生成
        //public event OrderEventHandler Order
        public event EventHandler Order
        {
            add
            {
                this.orderEventHandler += value;
            }
            remove
            {
                this.orderEventHandler -= value;
            }
        }

        public double Bill { get; set; }

        public void PayBill()
        {
            Console.WriteLine("I Will pay ${0}", this.Bill);
        }

        public void WalkIn()
        {
            Console.WriteLine("Walk into the restaurant");
        }

        public void SitDown()
        {
            Console.WriteLine("Sit Down");
        }

        public void Think()
        {
            for (int i = 5; i > 0; i--)
            {
                Console.WriteLine("Let me think ...");
                Thread.Sleep(1000);
            }
            this.OnOrder("全坤套餐","large");
        }

        protected void OnOrder(string DishName, string Size)
        {
            if (this.orderEventHandler != null)
            {
                OrderEventAgrs e = new OrderEventAgrs();
                e.DishName = DishName;
                e.Size = Size;
                //触发委托方法  waiter action
                this.orderEventHandler.Invoke(this, e);
            }
        }

        public void Action()
        {
            Console.ReadLine();
            this.WalkIn();
            this.SitDown();
            this.Think();
        }


    }



    public class Waiter
    {
        internal void Action(object sender, EventArgs e)
        {
            Customer customer = sender as Customer;
            OrderEventAgrs orderInfo = e as OrderEventAgrs;
            Console.WriteLine("I Will Serve the dish -{0}", orderInfo.DishName);
            double price = 10;
            switch (orderInfo.Size)
            {
                case "small":
                    price = price * 0.5;
                    break;
                case "large":
                    price = price * 1.5;
                    break;
                default:
                    break;
            }

            customer.Bill = price;
        }
    }
}
